﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using MetaSharp.Transformation.Properties;
using System.Threading.Tasks;

namespace MetaSharp.Transformation.Tests.Patterns
{
	public class ArrayTests
	{
		[Fact]
		public async Task MatchesExplicitEmptyArraySuccessfully()
		{
            var p = Pattern.Array(Pattern.Not(Pattern.Any()));
            var m = await Pattern.Match(p, new[] { new object[0] });
			Assert.True(m.Matched);
		}

		[Fact]
		public async Task MatchesImplicitEmptyArraySuccessfully()
        {
            var p = Pattern.Array();
            var m = await Pattern.Match(p, new[] { new object[0] });
            Assert.True(m.Matched);
        }

		[Fact]
		public async Task MatchesArrayWithOneItem()
        {
            var p = Pattern.Array(Pattern.Any());
            var m = await Pattern.Match(p, new[] { new object[] { 7 } });
            Assert.Equal(7, m.Value);
		}

		[Fact]
		public async Task MatchesArrayWithTwoItems()
        {
            var expected = new object[] { 7, "foo" };
            var p = Pattern.Array(Pattern.And(Pattern.Any(), Pattern.Any()));
            var m = await Pattern.Match(p, new[] { expected });
            Assert.Equal(expected, (object[])m.Value);
		}

		[Fact]
		public async Task ReadsInnerArrayCorrectly()
		{
            var p = Pattern.Array(Pattern.Array(Pattern.Any()));
            var m = await Pattern.Match(p, new[] { new[] { new [] { 7 } } });
			Assert.Equal(7, m.Value);
		}

		[Fact]
		public async Task ReadsCorrectNumberOfElements()
		{
            var p = Pattern.And(
                Pattern.Any(),
                Pattern.Array(Pattern.Any()),
                Pattern.Any());
            var m = await Pattern.Match(p, new object[] { 7, new[] { 11 }, 23 });

            var values = (object[])m.Value;
            Assert.Equal(new object[] { 7, 11, 23 }, values);
		}

		[Fact]
		public async Task MatchesNonArrayEnumerables()
		{
            var p = Pattern.Array();
            var m = await Pattern.Match(p, new[] { new List<object>() });
            Assert.True(m.Matched);
		}

		[Fact]
		public async Task PartiallyMatchedArrayFails()
		{
            var p = Pattern.Array(Pattern.Any());
            var m = await Pattern.Match(p, new[] { new[] { 7, 11 } });
			Assert.False(m.Matched);
		}

		[Fact]
		public async Task EmptyInputAlwaysReturnsNull()
		{
            var p = Pattern.Array();
            var m = await Pattern.Match(p, new object[] { new object[] { } });
			Assert.Null(m.Value);
		}

		[Fact]
		public async Task MatchOutsideOfArrayFails()
		{
            var p = Pattern.Array(
                Pattern.And(
                    Pattern.Any(),
                    Pattern.Any()));
            var m = await Pattern.Match(p, new object[] { new[] { 7 }, 11 });

			Assert.False(m.Matched);
		}
	}
}
